package com.cskaoyan.javase.oop3._2inner._3local._3notice;

/**
 * @description: 使用局部内部类的注意事项
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 首先强调一点:
 *      匿名内部类和lambda表达式都是特殊的局部内部类,这个注意事项它们仍然符合
 *
 * 注意点是: 在局部内部类中访问(装有内部类)方法的局部变量,这个时候,该变量要么直接声明final,要么不能修改它
 * 为什么会出现这个现象呢?
 * 生命周期的冲突: 如果方法出栈局部变量销毁,而对象仍然在调用方法,那么它去哪里找局部变量a呢?
 *  JVM在创建内部类对象时,如果局部内部类对象访问了方法的局部变量,JVM会自动把该局部变量作为对象的成员变量给"塞"到成员列表中,这样就解决了生命周期的冲突问题
 *
 *  解决了生命周期问题，又引入了新的问题： 拷贝的成员变量和方法的局部变量"同步"问题
 *      如果允许内部类的方法去修改局部变量的取值,虽然实际上修改的是自己的成员变量,
 *      但仍然需要把修改的值同步给局部变量
 *      但是Java的设计者可能觉得同步过于麻烦,或者实现不了
 *      没有采取同步的方式
 *      而是直接禁止修改局部变量的取值,那么这样它们的值就不会需要同步了
 *
 * 在Java8之前,只要在内部类当中访问局部变量,该变量就必须显式声明final
 * 在Java8之后,程序员不需要这么做,但是在底层该局部变量仍然是final修饰的
 *      这可以看成是一种"语法糖"
 *
 *
 */
public class Demo {
}

class EnclosedClazz {

    public void test() {
        int a = 10; //方法栈帧中的局部变量,随着方法"同生共死"
        class Inner {
            int a = 20;
            //属于对象调用的成员,只要对象还存在,它都有可能被调用
            //生命周期的冲突: 如果方法出栈局部变量销毁,而对象仍然在调用方法,那么它去哪里找局部变量a呢?
            public void testInner() {
                //Variable 'a' is accessed from within inner class, needs to be final or effectively final
                //System.out.println(a++);
                System.out.println(a);
            }
        }
    }

}